home *** CD-ROM | disk | FTP | other *** search
/ PC Format (South-Africa) 2001 June / PCFJune.iso / mweb / MWEB Utils / ws295sdk.exe / Ws2sdkzp.exe / SAMPLES / LAYERED / DWORKER.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-06  |  42.6 KB  |  1,417 lines

  1. /*++
  2.  
  3.      Copyright (c) 1996 Intel Corporation
  4.      Copyright (c) 1996 Microsoft Corporation
  5.      All Rights Reserved
  6.  
  7.      Permission is granted to use, copy and distribute this software and
  8.      its documentation for any purpose and without fee, provided, that
  9.      the above copyright notice and this statement appear in all copies.
  10.      Intel makes no representations about the suitability of this
  11.      software for any purpose.  This software is provided "AS IS."
  12.  
  13.      Intel specifically disclaims all warranties, express or implied,
  14.      and all liability, including consequential and other indirect
  15.      damages, for the use of this software, including liability for
  16.      infringement of any proprietary rights, and including the
  17.      warranties of merchantability and fitness for a particular purpose.
  18.      Intel does not assume any responsibility for any errors which may
  19.      appear in this software nor any responsibility to update it.
  20.  
  21.  
  22. Module Name:
  23.  
  24.  
  25. Abstract:
  26.  
  27.  
  28. --*/
  29.  
  30. #include "precomp.h"
  31.  
  32.  
  33. PDOVERLAPPEDSTRUCTMGR gOverlappedManager;
  34.  
  35.  
  36.  
  37.  
  38. VOID
  39. CALLBACK
  40. APCProc(
  41.     DWORD Context
  42.     )
  43. /*++
  44. Routine Description:
  45.  
  46.     This routine unpacks the context value passed to WPUQueueApc() and calls
  47.     the users completion function. This function is called in the clients
  48.     thread context.
  49.  
  50. Arguments:
  51.  
  52.     Context - The context value passed to WPUQueueApc().
  53.  
  54. Return Value:
  55.  
  56.     None
  57.  
  58. --*/
  59. {
  60.     LPOVERLAPPED                        lpOverlapped;
  61.     LPWSAOVERLAPPED_COMPLETION_ROUTINE  UserCompletionRoutine;
  62.  
  63.     lpOverlapped = (LPOVERLAPPED) Context;
  64.     UserCompletionRoutine =
  65.         (LPWSAOVERLAPPED_COMPLETION_ROUTINE)lpOverlapped->Internal;
  66.     lpOverlapped->Internal = lpOverlapped->Offset; // To make sure it
  67.                                                    // in no longer is 
  68.                                                    // WSS_OPERATION_IN_PROGRESS
  69.     UserCompletionRoutine (
  70.         lpOverlapped->Offset,
  71.         lpOverlapped->InternalHigh,
  72.         lpOverlapped,
  73.         lpOverlapped->OffsetHigh
  74.         );
  75.  
  76.  
  77. }
  78.  
  79. VOID
  80. CALLBACK
  81. OverlappedCompletionProc(
  82.     DWORD  dwError,
  83.     DWORD  cbTransferred,
  84.     LPWSAOVERLAPPED lpOverlapped,
  85.     DWORD dwFlags
  86.     )
  87. /*++
  88. Routine Description:
  89.  
  90.     This routine is the completion routine for all overlapped operations
  91.     initiated with the lower level provider.
  92.  
  93. Arguments:
  94.  
  95.     dwError - The error code for the overlapped operation.
  96.  
  97.     cbTransferred - The number of bytes transfered by the overlapped
  98.                     operation.
  99.  
  100.     lpOverlapped - a pointer to the WSAOVERLAPPED struct associated with the
  101.                    overlapped operation.
  102.  
  103.     dwFlags -  Not Used must be zero.
  104.  
  105. Return Value:
  106.  
  107.     None
  108.  
  109. --*/
  110. {
  111.     INT                                Errno;
  112.     PINTERNALOVERLAPPEDSTRUCT           OverlappedStruct;
  113.     DWORD                               OperationType;
  114.     PDPROVIDER                           Provider;
  115.     SOCKET                               ProviderSocket, Socket;
  116.     WSATHREADID                           UserThreadId;
  117.     LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine;
  118.     LPWSAOVERLAPPED                       UserOverlappedStruct;
  119.  
  120.  
  121.  
  122.     // Get the stored overlapped operation parameters
  123.     OverlappedStruct = gOverlappedManager->GetInternalOverlappedStructure(
  124.                         lpOverlapped);
  125.     // If the completed operation was a recieve operation copy the internal
  126.     // buffers into the users buffers.
  127.     if (OverlappedStruct != NULL){
  128.         OperationType = OverlappedStruct->iolOperationType;
  129.         Socket = OverlappedStruct->iolSocket;
  130.         Provider = OverlappedStruct->iolProvider;
  131.         ProviderSocket = OverlappedStruct->iolProviderSocket;
  132.         UserCompletionRoutine = OverlappedStruct->iolUserCompletionRoutine;
  133.         UserOverlappedStruct = OverlappedStruct->iolUserOverlappedStruct;
  134.         UserThreadId = OverlappedStruct->iolUserThreadId;
  135.         
  136.         if (dwError==WSA_IO_PENDING)
  137.             Provider->WSPGetOverlappedResult (
  138.                     ProviderSocket,
  139.                     lpOverlapped,
  140.                     &cbTransferred,
  141.                     FALSE,
  142.                     &dwFlags,
  143.                     (int *)&dwError);
  144.                                 
  145.  
  146.         switch (OperationType) {
  147.         case WSP_RECV:
  148.         case WSP_RECVFROM:
  149.             gBufferManager->CopyBuffer(
  150.                 (OverlappedStruct->iolInternalBufferCount <= MAX_FAST_BUFS)
  151.                     ? &OverlappedStruct->iolInternalBuffers[0]
  152.                     : OverlappedStruct->iolpInternalBuffers,
  153.                 OverlappedStruct->iolInternalBufferCount,
  154.                 0,
  155.                 cbTransferred,
  156.                 (OverlappedStruct->iolUserBufferCount <= MAX_FAST_BUFS)
  157.                     ? &OverlappedStruct->iolUserBuffers[0]
  158.                     : OverlappedStruct->iolpUserBuffers,
  159.                 OverlappedStruct->iolUserBufferCount,
  160.                 0);
  161.             gBufferManager->FreeBuffer(
  162.                 (OverlappedStruct->iolInternalBufferCount <= MAX_FAST_BUFS)
  163.                     ? &OverlappedStruct->iolInternalBuffers[0]
  164.                     : OverlappedStruct->iolpInternalBuffers,
  165.                 OverlappedStruct->iolInternalBufferCount);
  166.             if (OverlappedStruct->iolUserBufferCount > MAX_FAST_BUFS)
  167.                 delete OverlappedStruct->iolpUserBuffers;
  168.             if (OverlappedStruct->iolInternalBufferCount > MAX_FAST_BUFS)
  169.                 delete OverlappedStruct->iolpInternalBuffers;
  170.             break;
  171.  
  172.         case WSP_SEND:
  173.         case WSP_SENDTO:
  174.             if (OverlappedStruct->iolUserBufferCount > MAX_FAST_BUFS)
  175.                 delete OverlappedStruct->iolpUserBuffers;
  176.             break;
  177.  
  178.         case WSP_IOCTL:
  179.             if ((OverlappedStruct->iolIoControlCode==SIO_GET_EXTENSION_FUNCTION_POINTER)
  180.                     && (NO_ERROR==Errno)) {
  181.                 Provider->InterceptExtensions (
  182.                                     OverlappedStruct->iolInputBuffer,
  183.                                     OverlappedStruct->iolOutputBuffer,
  184.                                     &Errno);
  185.             }
  186.             break;
  187.         }
  188.  
  189.         gOverlappedManager->FreeOverlappedStruct (lpOverlapped);
  190.  
  191.  
  192.         // If the user requested completion routine notification of the I/O
  193.         // completion queue an APC to the user thread else signal the users
  194.         // event.
  195.         if (UserCompletionRoutine){
  196.             UserOverlappedStruct->InternalHigh = cbTransferred;
  197.             UserOverlappedStruct->Offset = dwError;
  198.             UserOverlappedStruct->OffsetHigh = dwFlags;
  199.  
  200.             // Changing Internal field to anything other than
  201.             // WSS_OPERATON_IN_PROGRESS indicates that operation
  202.             // is completed and results can be read by WSPGetOverlappedResult,
  203.             // That's why we set this field last (after updating all others)
  204.             // Note that event if address of user completion routine is 
  205.             // equal to WSS_OPERATON_IN_PROGRESS (numericall), we are still
  206.             // safe, because we'll update it again in our completion routine
  207.             // Also, generally if application specifies completion routine,
  208.             // it should not use WSAGetOverlappedResult, so essentially by
  209.             // doing all of this we are just making our code bullet proof
  210.             UserOverlappedStruct->Internal = (DWORD)UserCompletionRoutine;
  211.  
  212.             gUpCallTable.lpWPUQueueApc(
  213.                 &UserThreadId,
  214.                 APCProc,
  215.                 (DWORD)UserOverlappedStruct,
  216.                 &Errno);
  217.  
  218.         } //if
  219.         else{
  220.             UserOverlappedStruct->Offset = dwError;
  221.             UserOverlappedStruct->OffsetHigh = dwFlags;
  222.                 // Internal and InternalHigh fields will be updated
  223.                 // by the WPUCompleteOverlappedRequest
  224.             lpWPUCompleteOverlappedRequest (
  225.                 Socket,
  226.                 UserOverlappedStruct,
  227.                 dwError,
  228.                 cbTransferred,
  229.                 &Errno);
  230.         } //else
  231.     } //if
  232. }
  233.  
  234.  
  235.  
  236. VOID
  237. InitiateOverlappedOperation (
  238.     PINTERNALOVERLAPPEDSTRUCT           OverlappedStruct,
  239.     LPWSAOVERLAPPED_COMPLETION_ROUTINE  CompletionProc,
  240.     LPWSATHREADID                       thread_id
  241.     )
  242. /*++
  243. Routine Description:
  244.  
  245.     Initiates overlapped operation with provider.
  246.  
  247. Arguments:
  248.  
  249.     OverlappedStruct    - packet operation parameters
  250.     CompletionProc      - routine to be invoked upon completion
  251.     thread_id           - id of the thread to which to post APC if any
  252. Return Value:
  253.  
  254.     NONE
  255. --*/
  256. {
  257.     DWORD                     BytesTransfered;
  258.     INT                       Errno;
  259.     INT                       ReturnCode;
  260.  
  261.     switch (OverlappedStruct->iolOperationType) {
  262.     case WSP_RECV:
  263.         ReturnCode = OverlappedStruct->iolProvider->WSPRecv(
  264.             OverlappedStruct->iolProviderSocket,
  265.             (OverlappedStruct->iolInternalBufferCount <= MAX_FAST_BUFS)
  266.                 ? &OverlappedStruct->iolInternalBuffers[0]
  267.                 : OverlappedStruct->iolpInternalBuffers,
  268.             OverlappedStruct->iolInternalBufferCount,
  269.             &BytesTransfered,
  270.             &OverlappedStruct->iolFlags,
  271.             &OverlappedStruct->iolInternalOverlappedStruct,
  272.             CompletionProc,
  273.             thread_id,
  274.             &Errno);
  275.         break;
  276.  
  277.     case WSP_RECVFROM:
  278.         ReturnCode = OverlappedStruct->iolProvider->WSPRecvFrom(
  279.             OverlappedStruct->iolProviderSocket,
  280.             (OverlappedStruct->iolInternalBufferCount <= MAX_FAST_BUFS)
  281.                 ? &OverlappedStruct->iolInternalBuffers[0]
  282.                 : OverlappedStruct->iolpInternalBuffers,
  283.             OverlappedStruct->iolInternalBufferCount,
  284.             &BytesTransfered,
  285.             &OverlappedStruct->iolFlags,
  286.             OverlappedStruct->iolSockAddr,
  287.             OverlappedStruct->iolSockAddrLenPtr,
  288.             &OverlappedStruct->iolInternalOverlappedStruct,
  289.             CompletionProc,
  290.             thread_id,
  291.             &Errno);
  292.         break;
  293.  
  294.     case WSP_SEND:
  295.          ReturnCode = OverlappedStruct->iolProvider->WSPSend(
  296.             OverlappedStruct->iolProviderSocket,
  297.             (OverlappedStruct->iolUserBufferCount <= MAX_FAST_BUFS)
  298.                 ? &OverlappedStruct->iolUserBuffers[0]
  299.                 : OverlappedStruct->iolpUserBuffers,
  300.             OverlappedStruct->iolUserBufferCount,
  301.             &BytesTransfered,
  302.             OverlappedStruct->iolFlags,
  303.             &OverlappedStruct->iolInternalOverlappedStruct,
  304.             CompletionProc,
  305.             thread_id,
  306.             &Errno);
  307.         break;
  308.     case WSP_SENDTO:
  309.         ReturnCode = OverlappedStruct->iolProvider->WSPSendTo(
  310.             OverlappedStruct->iolProviderSocket,
  311.             (OverlappedStruct->iolUserBufferCount <= MAX_FAST_BUFS)
  312.                 ? &OverlappedStruct->iolUserBuffers[0]
  313.                 : OverlappedStruct->iolpUserBuffers,
  314.             OverlappedStruct->iolUserBufferCount,
  315.             &BytesTransfered,
  316.             OverlappedStruct->iolFlags,
  317.             OverlappedStruct->iolSockAddr,
  318.             OverlappedStruct->iolSockAddrLen,
  319.             &OverlappedStruct->iolInternalOverlappedStruct,
  320.             CompletionProc,
  321.             thread_id,
  322.             &Errno);
  323.         break;
  324.  
  325.     case WSP_IOCTL:
  326.         ReturnCode = OverlappedStruct->iolProvider->WSPIoctl(
  327.             OverlappedStruct->iolProviderSocket,
  328.             OverlappedStruct->iolIoControlCode,
  329.             OverlappedStruct->iolInputBuffer,
  330.             OverlappedStruct->iolInputBufferLength,
  331.             OverlappedStruct->iolOutputBuffer,
  332.             OverlappedStruct->iolOutputBufferLength,
  333.             &BytesTransfered,
  334.             &OverlappedStruct->iolInternalOverlappedStruct,
  335.             CompletionProc,
  336.             thread_id,
  337.             &Errno);
  338.         break;
  339.     case ACCEPT_EX:
  340.         ReturnCode = OverlappedStruct->iolProvider->AcceptEx (
  341.             OverlappedStruct->iolListenSocket,
  342.             OverlappedStruct->iolAcceptSocket,
  343.             OverlappedStruct->iolOutputBuffer,
  344.             OverlappedStruct->iolOutputBufferLength,
  345.             OverlappedStruct->iolLocalAddressLength,
  346.             OverlappedStruct->iolRemoteAddressLength,
  347.             &BytesTransfered,
  348.             &OverlappedStruct->iolInternalOverlappedStruct,
  349.             &Errno);
  350.         break;
  351.     case TRANSMIT_FILE:
  352.         ReturnCode = OverlappedStruct->iolProvider->TransmitFile (
  353.             OverlappedStruct->iolProviderSocket,
  354.             OverlappedStruct->iolFileHandle,
  355.             OverlappedStruct->iolBytesToWrite,
  356.             OverlappedStruct->iolBytesPerSend,
  357.             &OverlappedStruct->iolInternalOverlappedStruct,
  358.             ((OverlappedStruct->iolTransmitBuffers.HeadLength!=0)
  359.                     || (OverlappedStruct->iolTransmitBuffers.TailLength!=0))
  360.                 ? &OverlappedStruct->iolTransmitBuffers
  361.                 : NULL,
  362.             OverlappedStruct->iolReserved,
  363.             &Errno);
  364.         break;
  365.     default:
  366.         assert (FALSE);
  367.         break;
  368.     } //switch
  369.  
  370.     // Complete ourselves if provider fails right away
  371.     if ((ReturnCode!=NO_ERROR) && (Errno!=WSA_IO_PENDING))
  372.         OverlappedCompletionProc (
  373.             Errno,
  374.             0,
  375.             &OverlappedStruct->iolInternalOverlappedStruct,
  376.             0);
  377.  
  378. }
  379.  
  380. DWORD
  381. WorkerThreadProc(
  382.     DWORD  Context
  383.     )
  384. /*++
  385. Routine Description:
  386.  
  387.     Thread procedure passed to CreatThread().
  388.  
  389. Arguments:
  390.  
  391.     Context - Context value passed to CreateThread().  The context value is the
  392.               worker thread object.
  393.  
  394. Return Value:
  395.  
  396.     The Return value of the worker thread
  397.  
  398. --*/
  399.  
  400. {
  401.     PDWORKERTHREAD            Thread;
  402.     HINSTANCE                 HModule;
  403.     DWORD                     ReturnCode;
  404.     HModule = LoadLibraryA (gLibraryName);
  405.  
  406.  
  407.     Thread = (PDWORKERTHREAD) Context;
  408.     ReturnCode = Thread->WorkerThreadProc();
  409.     delete Thread;
  410.     
  411.     DEBUGF( DBG_TRACE,
  412.             ("Exiting worker thread.\n"));
  413.     FreeLibraryAndExitThread (HModule, ReturnCode);
  414.     return 0;   // Keep compiler happy
  415. }
  416.  
  417.  
  418.  
  419.  
  420.  
  421. DWORKERTHREAD::DWORKERTHREAD()
  422. /*++
  423. Routine Description:
  424.  
  425.     Creates any internal state.
  426.  
  427. Arguments:
  428.  
  429.     None
  430.  
  431. Return Value:
  432.  
  433.     None
  434.  
  435. --*/
  436.  
  437. {
  438.     m_exit_thread = FALSE;
  439.     m_thread_count = NULL;
  440.     m_wakeup_semaphore = NULL;
  441.     m_completion_port = NULL;
  442.  
  443.     InitializeCriticalSection(
  444.         &m_overlapped_operation_queue_lock);
  445.  
  446.     InitializeListHead(
  447.         &m_overlapped_operation_queue);
  448. }
  449.  
  450. VOID
  451. DWORKERTHREAD::Destroy (
  452.     )
  453. /*++
  454. Routine Description:
  455.  
  456.     Initiates destruction of the DWORKERTHREAD object.
  457.     This can't be done syncronously in destructor because this
  458.     will require waiting for thread object to exit which we want
  459.     to avoid.
  460.  
  461. Arguments:
  462.  
  463.     NONE
  464.  
  465. Return Value:
  466.  
  467.     NONE
  468. --*/
  469. {
  470.     // If we made it through Initialize. Wake up our threads tell them to exit.
  471.     if (m_thread_count>0){
  472.         m_exit_thread = TRUE;
  473.         if (m_completion_port) {
  474.             static OVERLAPPED overlapped;
  475.             PostQueuedCompletionStatus (m_completion_port,
  476.                                     0,
  477.                                     INVALID_SOCKET,
  478.                                     &overlapped
  479.                                     );
  480.         }
  481.         else {
  482.             ReleaseSemaphore (m_wakeup_semaphore, m_thread_count, NULL);
  483.         }
  484.         m_thread_count = 0;
  485.     }
  486. }
  487.  
  488.  
  489. DWORKERTHREAD::~DWORKERTHREAD()
  490. /*++
  491. Routine Description:
  492.  
  493.     destroys any internal state.
  494.  
  495. Arguments:
  496.  
  497.     None
  498.  
  499. Return Value:
  500.  
  501.     None
  502.  
  503. --*/
  504. {
  505.  
  506.     if (m_completion_port) {
  507.         CloseHandle (m_completion_port);
  508.         m_completion_port = NULL;
  509.     }
  510.     else if (m_wakeup_semaphore){
  511.         CloseHandle(m_wakeup_semaphore);
  512.         m_wakeup_semaphore = NULL;
  513.     } //if
  514.  
  515.  
  516.     if (gOverlappedManager) {
  517.         delete(gOverlappedManager);
  518.         gOverlappedManager = NULL;
  519.     }
  520.  
  521.     DeleteCriticalSection(
  522.         &m_overlapped_operation_queue_lock);
  523.  
  524.  
  525.     DEBUGF( DBG_TRACE,
  526.             ("Destroyed worker thread object\n"));
  527. }
  528.  
  529.  
  530.  
  531. INT
  532. DWORKERTHREAD::Initialize(
  533.  
  534.     )
  535. /*++
  536. Routine Description:
  537.  
  538.     Initializes the DWORKERTHREAD object.
  539.  
  540. Arguments:
  541.  
  542.     NONE
  543.  
  544. Return Value:
  545.  
  546.     If no error occurs, Initialize() returns NO_ERROR.  Otherwise the value
  547.     SOCKET_ERROR  is  returned,  and  a  specific  error  code  is available in
  548.     lpErrno.
  549.  
  550. --*/
  551. {
  552.     INT ReturnCode =WSAENOBUFS;
  553.     DWORD           ThreadId;
  554.     HANDLE          hThread;
  555.     SYSTEM_INFO     info;
  556.     DWORD            max_threads;
  557.  
  558.     DEBUGF( DBG_TRACE,
  559.             ("Initializing worker thread \n"));
  560.  
  561.     m_completion_port = CreateIoCompletionPort (
  562.                                 INVALID_HANDLE_VALUE,
  563.                                 NULL,
  564.                                 0,
  565.                                 0);
  566.     if (m_completion_port!=NULL) {
  567.         ReturnCode = NO_ERROR;
  568.         // Don't need extra worker threads if we use completion
  569.         // port -> IO will be initiated/executed in the context
  570.         // of the original client thread and the worker thread
  571.         // will only be used to receive and redirect completion 
  572.         // notification.
  573.         max_threads = 1;
  574.     }
  575.     else {
  576.         // Create the semaphore we will use to communicat with the worker thread.
  577.         m_wakeup_semaphore = CreateSemaphore(
  578.             NULL,
  579.             0,
  580.             MAXLONG,
  581.             NULL);
  582.         if ( m_wakeup_semaphore){
  583.             GetSystemInfo (&info);
  584.             max_threads = info.dwNumberOfProcessors;
  585.             ReturnCode = NO_ERROR;
  586.         } //if
  587.     } // if
  588.  
  589.  
  590.     if (NO_ERROR == ReturnCode){
  591.         gOverlappedManager = new DOVERLAPPEDSTRUCTMGR;
  592.         if (gOverlappedManager!=NULL) {
  593.             ReturnCode = gOverlappedManager->Initialize();
  594.         }
  595.         else
  596.             ReturnCode = WSAENOBUFS;
  597.     }
  598.  
  599.     //
  600.     // Create the worker threads.
  601.     //
  602.     if (NO_ERROR == ReturnCode){
  603.         for (m_thread_count=0; m_thread_count<max_threads; m_thread_count++) {
  604.             hThread = CreateThread(
  605.                 NULL,
  606.                 0,
  607.                 (LPTHREAD_START_ROUTINE)::WorkerThreadProc,
  608.                 this,
  609.                 0,
  610.                 &ThreadId);
  611.             if (hThread!=NULL)
  612.                 CloseHandle (hThread);
  613.             else
  614.                 break;
  615.         } // for
  616.         if (m_thread_count>0)
  617.             ReturnCode = NO_ERROR;
  618.         else
  619.             ReturnCode = WSAENOBUFS;
  620.  
  621.     } //if
  622.  
  623.     if (NO_ERROR != ReturnCode){
  624.         //Cleanup any resources we may have allocated.
  625.         if (m_thread_count>0){
  626.             m_exit_thread = TRUE;
  627.             ReleaseSemaphore(m_wakeup_semaphore, m_thread_count, NULL);
  628.         } //if
  629.  
  630.         if (gOverlappedManager) {
  631.             delete gOverlappedManager;
  632.             gOverlappedManager = NULL;
  633.         }
  634.  
  635.         if (m_wakeup_semaphore) {
  636.             CloseHandle (m_wakeup_semaphore);
  637.             m_wakeup_semaphore = NULL;
  638.         } // if
  639.  
  640.     } //if
  641.  
  642.     return(ReturnCode);
  643. } //Initailize
  644.  
  645.  
  646.  
  647.  
  648. DWORD
  649. DWORKERTHREAD::WorkerThreadProc()
  650. /*++
  651. Routine Description:
  652.  
  653.     The thread procedure for this object.
  654.  
  655. Arguments:
  656.  
  657.     NONE
  658.  
  659. Return Value:
  660.  
  661.     NO_ERROR
  662.  
  663. --*/
  664. {
  665.     INT   Errno;
  666.  
  667.     gUpCallTable.lpWPUOpenCurrentThread(
  668.         &m_thread_id,
  669.         &Errno);
  670.  
  671.     while (!m_exit_thread){
  672.         if (m_completion_port) {
  673.             BOOL            result;
  674.             LPOVERLAPPED    lpOverlapped;
  675.             DWORD           key, cbTransferred;
  676.             result = GetQueuedCompletionStatus (
  677.                         m_completion_port,
  678.                         &cbTransferred,
  679.                         &key,
  680.                         &lpOverlapped,
  681.                         INFINITE
  682.                         );
  683.             if (m_exit_thread) {
  684.                 DEBUGF (DBG_TRACE, ("Worker thread received signal to exit.\n"));
  685.                 break;
  686.             } // if
  687.             else if ((key!=-1) && (lpOverlapped!=NULL)) {
  688.                 OverlappedCompletionProc (
  689.                     WSA_IO_PENDING,
  690.                     cbTransferred,
  691.                     lpOverlapped,
  692.                     0);
  693.             } //else if
  694.  
  695.         } // if
  696.         else {
  697.             DWORD                       ReturnCode;
  698.             PINTERNALOVERLAPPEDSTRUCT   OverlappedStruct;
  699.             ReturnCode = WaitForSingleObjectEx(
  700.                 m_wakeup_semaphore,
  701.                 INFINITE,
  702.                 TRUE);
  703.             if (m_exit_thread) {
  704.                 DEBUGF (DBG_TRACE, ("Worker thread received signal to exit.\n"));
  705.                 break;
  706.             } // if
  707.             else if (ReturnCode == WAIT_OBJECT_0){
  708.  
  709.                 // Is there a queued overlapped operation that needs to be
  710.                 // initiated.
  711.                 OverlappedStruct = NextOverlappedOperation();
  712.  
  713.                 if (OverlappedStruct){
  714.                     InitiateOverlappedOperation (
  715.                         OverlappedStruct,
  716.                         OverlappedCompletionProc,
  717.                         &m_thread_id);
  718.                 } //if
  719.             } // else if
  720.         } //else
  721.     } //while
  722.  
  723.     gUpCallTable.lpWPUCloseThread(
  724.         &m_thread_id,
  725.         &Errno);
  726.  
  727.     return(NO_ERROR);
  728. }
  729.  
  730. INT
  731. DWORKERTHREAD::QueueOverlappedRecv(
  732.     PDSOCKET                           Socket,
  733.     LPWSABUF                           UserBuffers,
  734.     DWORD                              UserBufferCount,
  735.     LPDWORD                            UserBytesRecvd,
  736.     LPDWORD                            UserFlags,
  737.     LPWSAOVERLAPPED                    UserOverlappedStruct,
  738.     LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine,
  739.     LPWSATHREADID                      UserThreadId,
  740.     LPWSABUF                           InternalBuffers,
  741.     DWORD                              InternalBufferCount,
  742.     LPINT                              Errno
  743.     )
  744. /*++
  745.  
  746. Routine Description:
  747.  
  748.     this routine allocates an internal overlapped structure stores its
  749.     arguments in the allocated structure and enqueues the structure for the
  750.     worker thread to complet the I/O operation.
  751.  
  752. Arguments:
  753.  
  754.     Socket      - Socket object
  755.  
  756.     UserBuffers - The pointer to the user buffer(s).
  757.  
  758.     UserBufferCount - The number of user buffers.
  759.  
  760.     UserBytesRecvd - The pointer to the user BytesRecvd parameter.
  761.  
  762.     UserFlags - A pointer to the user flags argument.
  763.  
  764.     UserOverlappedStruct - The user overlapped struct pointer.
  765.  
  766.     UserCompletionRoutine - The user overlapped completion routine.
  767.  
  768.     UserThreadId - The user thread ID.
  769.  
  770.     InternalBuffers - A pointer to our internal buffer(s).
  771.  
  772.     InternalBufferCount - The number of internal buffers.
  773.  
  774.     Errno - A pointer to the user errno parameter.
  775.  
  776. Return Value:
  777.  
  778.     NO_ERROR on success else a valid winsock2 error code.
  779.  
  780. --*/
  781. {
  782.     INT ReturnCode;
  783.  
  784.     PINTERNALOVERLAPPEDSTRUCT OverlappedStruct;
  785.  
  786.     ReturnCode = SOCKET_ERROR;
  787.     *Errno = WSAENOBUFS;
  788.  
  789.     OverlappedStruct =
  790.         gOverlappedManager->AllocateOverlappedStruct();
  791.     if (OverlappedStruct){
  792.         OverlappedStruct->iolOperationType = WSP_RECV;
  793.         OverlappedStruct->iolSocket = Socket->GetSocketHandle ();
  794.         OverlappedStruct->iolProvider = Socket->GetDProvider();
  795.         OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket ();
  796.         OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct;
  797.         OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine;
  798.         OverlappedStruct->iolUserThreadId = *UserThreadId;
  799.         if (UserBufferCount<=MAX_FAST_BUFS)
  800.             memcpy (OverlappedStruct->iolUserBuffers, UserBuffers,
  801.                         sizeof (WSABUF)*UserBufferCount);
  802.         else {
  803.             OverlappedStruct->iolpUserBuffers = new WSABUF[UserBufferCount];
  804.             if (OverlappedStruct->iolpUserBuffers==NULL) {
  805.                 gOverlappedManager->FreeOverlappedStruct (
  806.                         &OverlappedStruct->iolInternalOverlappedStruct);
  807.                 return ReturnCode;
  808.             }
  809.             memcpy (OverlappedStruct->iolpUserBuffers, UserBuffers,
  810.                         sizeof (WSABUF)*UserBufferCount);
  811.         }
  812.         OverlappedStruct->iolUserBufferCount = UserBufferCount;
  813.         if (InternalBufferCount<=MAX_FAST_BUFS)
  814.             memcpy (OverlappedStruct->iolInternalBuffers, InternalBuffers,
  815.                         sizeof (WSABUF)*InternalBufferCount);
  816.         else {
  817.             OverlappedStruct->iolpInternalBuffers = new WSABUF[InternalBufferCount];
  818.             if (OverlappedStruct->iolpInternalBuffers==NULL) {
  819.                 if (UserBufferCount>MAX_FAST_BUFS)
  820.                     delete OverlappedStruct->iolpUserBuffers;
  821.                 gOverlappedManager->FreeOverlappedStruct (
  822.                         &OverlappedStruct->iolInternalOverlappedStruct);
  823.                 return ReturnCode;
  824.             }
  825.             memcpy (OverlappedStruct->iolpInternalBuffers, InternalBuffers,
  826.                         sizeof (WSABUF)*InternalBufferCount);
  827.         }
  828.         OverlappedStruct->iolInternalBufferCount = InternalBufferCount;
  829.         OverlappedStruct->iolFlags = *UserFlags;
  830.         AddOverlappedOperation(
  831.             Socket,
  832.             OverlappedStruct);
  833.         *Errno = WSA_IO_PENDING;
  834.  
  835.     } //if
  836.     return(ReturnCode);
  837. }
  838.  
  839.  
  840. INT
  841. DWORKERTHREAD::QueueOverlappedRecvFrom(
  842.     PDSOCKET                           Socket,
  843.     LPWSABUF                           UserBuffers,
  844.     DWORD                              UserBufferCount,
  845.     LPDWORD                            UserBytesRecvd,
  846.     LPDWORD                            UserFlags,
  847.     struct sockaddr FAR *              UserFrom,
  848.     LPINT                              UserFromLen,
  849.     LPWSAOVERLAPPED                    UserOverlappedStruct,
  850.     LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine,
  851.     LPWSATHREADID                      UserThreadId,
  852.     LPWSABUF                           InternalBuffers,
  853.     DWORD                              InternalBufferCount,
  854.     LPINT                              Errno
  855.     )
  856. /*++
  857.  
  858. Routine Description:
  859.  
  860.     this routine allocates an internal overlapped structure stores its
  861.     arguments in the allocated structure and enqueues the structure for the
  862.     worker thread to complet the I/O operation.
  863.  
  864. Arguments:
  865.  
  866.     Socket      - Socket object
  867.  
  868.     UserBuffers - The pointer to the user buffer(s).
  869.  
  870.     UserBufferCount - The number of user buffers.
  871.  
  872.     UserBytesRecvd - The pointer to the user BytesRecvd parameter.
  873.  
  874.     UserFlags - A pointer to the user flags argument.
  875.  
  876.     UserFrom  - A pinter to the user sockaddr structure,
  877.  
  878.     UserFromLen - A pointer to the length of UserFrom.
  879.  
  880.     UserOverlappedStruct - The user overlapped struct pointer.
  881.  
  882.     UserCompletionRoutine - The user overlapped completion routine.
  883.  
  884.     UserThreadId - The user thread ID.
  885.  
  886.     InternalBuffers - A pointer to our internal buffer(s).
  887.  
  888.     InternalBufferCount - The number of internal buffers.
  889.  
  890.     Errno - A pointer to the user errno parameter.
  891.  
  892. Return Value:
  893.  
  894.     NO_ERROR on success else a valid winsock2 error code.
  895.  
  896. --*/
  897. {
  898.     INT                       ReturnCode;
  899.     PINTERNALOVERLAPPEDSTRUCT OverlappedStruct;
  900.  
  901.     ReturnCode = SOCKET_ERROR;
  902.     *Errno = WSAENOBUFS;
  903.  
  904.     OverlappedStruct =
  905.         gOverlappedManager->AllocateOverlappedStruct();
  906.     if (OverlappedStruct){
  907.         OverlappedStruct->iolOperationType = WSP_RECVFROM;
  908.         OverlappedStruct->iolSocket = Socket->GetSocketHandle ();
  909.         OverlappedStruct->iolProvider = Socket->GetDProvider();
  910.         OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket ();
  911.         OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct;
  912.         OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine;
  913.         OverlappedStruct->iolUserThreadId = *UserThreadId;
  914.         if (UserBufferCount<=MAX_FAST_BUFS)
  915.             memcpy (OverlappedStruct->iolUserBuffers, UserBuffers,
  916.                         sizeof (WSABUF)*UserBufferCount);
  917.         else {
  918.             OverlappedStruct->iolpUserBuffers = new WSABUF[UserBufferCount];
  919.             if (OverlappedStruct->iolpUserBuffers==NULL) {
  920.                 gOverlappedManager->FreeOverlappedStruct (
  921.                         &OverlappedStruct->iolInternalOverlappedStruct);
  922.                 return ReturnCode;
  923.             }
  924.             memcpy (OverlappedStruct->iolpUserBuffers, UserBuffers,
  925.                         sizeof (WSABUF)*UserBufferCount);
  926.         }
  927.         OverlappedStruct->iolUserBufferCount = UserBufferCount;
  928.         if (InternalBufferCount<=MAX_FAST_BUFS)
  929.             memcpy (OverlappedStruct->iolInternalBuffers, InternalBuffers,
  930.                         sizeof (WSABUF)*InternalBufferCount);
  931.         else {
  932.             OverlappedStruct->iolpInternalBuffers = new WSABUF[InternalBufferCount];
  933.             if (OverlappedStruct->iolpInternalBuffers==NULL) {
  934.                 if (UserBufferCount>MAX_FAST_BUFS)
  935.                     delete OverlappedStruct->iolpUserBuffers;
  936.                 gOverlappedManager->FreeOverlappedStruct (
  937.                         &OverlappedStruct->iolInternalOverlappedStruct);
  938.                 return ReturnCode;
  939.             }
  940.             memcpy (OverlappedStruct->iolpInternalBuffers, InternalBuffers,
  941.                         sizeof (WSABUF)*InternalBufferCount);
  942.         }
  943.         OverlappedStruct->iolInternalBufferCount = InternalBufferCount;
  944.         OverlappedStruct->iolFlags = *UserFlags;
  945.         OverlappedStruct->iolSockAddr = UserFrom;
  946.         OverlappedStruct->iolSockAddrLenPtr = UserFromLen;
  947.  
  948.         AddOverlappedOperation(
  949.             Socket,
  950.             OverlappedStruct);
  951.         *Errno = WSA_IO_PENDING;
  952.  
  953.     } //if
  954.     return(ReturnCode);
  955. }
  956.  
  957. INT
  958. DWORKERTHREAD::QueueOverlappedSend(
  959.     PDSOCKET                           Socket,
  960.     LPWSABUF                           UserBuffers,
  961.     DWORD                              UserBufferCount,
  962.     LPDWORD                            UserBytesSent,
  963.     DWORD                              UserFlags,
  964.     LPWSAOVERLAPPED                    UserOverlappedStruct,
  965.     LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine,
  966.     LPWSATHREADID                      UserThreadId,
  967.     LPINT           Errno
  968.     )
  969. /*++
  970.  
  971. Routine Description:
  972.  
  973.     this routine allocates an internal overlapped structure stores its
  974.     arguments in the allocated structure and enqueues the structure for the
  975.     worker thread to complet the I/O operation.
  976.  
  977. Arguments:
  978.  
  979.     Socket      - Socket object
  980.  
  981.     UserBuffers - The pointer to the user buffer(s).
  982.  
  983.     UserBufferCount - The number of user buffers.
  984.  
  985.     UserBytesSent - The pointer to the user BytesSent parameter.
  986.  
  987.     UserFlags - The user flags .
  988.  
  989.     UserOverlappedStruct - The user overlapped struct pointer.
  990.  
  991.     UserCompletionRoutine - The user overlapped completion routine.
  992.  
  993.     UserThreadId - The user thread ID.
  994.  
  995.     InternalBuffers - A pointer to our internal buffer(s).
  996.  
  997.     InternalBufferCount - The number of internal buffers.
  998.  
  999.     Errno - A pointer to the user errno parameter.
  1000.  
  1001. Return Value:
  1002.  
  1003.     NO_ERROR on success else a valid winsock2 error code.
  1004.  
  1005. --*/
  1006. {
  1007.     INT                       ReturnCode;
  1008.     PINTERNALOVERLAPPEDSTRUCT OverlappedStruct;
  1009.  
  1010.     ReturnCode = SOCKET_ERROR;
  1011.     *Errno = WSAENOBUFS;
  1012.  
  1013.     OverlappedStruct =
  1014.         gOverlappedManager->AllocateOverlappedStruct();
  1015.     if (OverlappedStruct){
  1016.         OverlappedStruct->iolOperationType = WSP_SEND;
  1017.         OverlappedStruct->iolSocket = Socket->GetSocketHandle ();
  1018.         OverlappedStruct->iolProvider = Socket->GetDProvider();
  1019.         OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket ();
  1020.         OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct;
  1021.         OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine;
  1022.         OverlappedStruct->iolUserThreadId = *UserThreadId;
  1023.         if (UserBufferCount<=MAX_FAST_BUFS)
  1024.             memcpy (OverlappedStruct->iolUserBuffers, UserBuffers,
  1025.                         sizeof (WSABUF)*UserBufferCount);
  1026.         else {
  1027.             OverlappedStruct->iolpUserBuffers = new WSABUF[UserBufferCount];
  1028.             if (OverlappedStruct->iolpUserBuffers==NULL) {
  1029.                 gOverlappedManager->FreeOverlappedStruct (
  1030.                         &OverlappedStruct->iolInternalOverlappedStruct);
  1031.                 return ReturnCode;
  1032.             }
  1033.             memcpy (OverlappedStruct->iolpUserBuffers, UserBuffers,
  1034.                         sizeof (WSABUF)*UserBufferCount);
  1035.         }
  1036.         OverlappedStruct->iolUserBufferCount = UserBufferCount;
  1037.         OverlappedStruct->iolFlags = UserFlags;
  1038.  
  1039.         AddOverlappedOperation(
  1040.             Socket,
  1041.             OverlappedStruct);
  1042.  
  1043.         *Errno = WSA_IO_PENDING;
  1044.  
  1045.     } //if
  1046.     return(ReturnCode);
  1047. }
  1048.  
  1049.  
  1050. INT
  1051. DWORKERTHREAD::QueueOverlappedSendTo(
  1052.     PDSOCKET                           Socket,
  1053.     LPWSABUF                           UserBuffers,
  1054.     DWORD                              UserBufferCount,
  1055.     LPDWORD                            UserBytesSent,
  1056.     DWORD                              UserFlags,
  1057.     const struct sockaddr FAR *        UserTo,
  1058.     INT                                UserToLen,
  1059.     LPWSAOVERLAPPED                    UserOverlappedStruct,
  1060.     LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine,
  1061.     LPWSATHREADID                      UserThreadId,
  1062.     LPINT                              Errno
  1063.     )
  1064. /*++
  1065.  
  1066. Routine Description:
  1067.  
  1068.     this routine allocates an internal overlapped structure stores its
  1069.     arguments in the allocated structure and enqueues the structure for the
  1070.     worker thread to complet the I/O operation.
  1071.  
  1072. Arguments:
  1073.  
  1074.     Socket      - Socket object
  1075.  
  1076.     UserBuffers - The pointer to the user buffer(s).
  1077.  
  1078.     UserBufferCount - The number of user buffers.
  1079.  
  1080.     UserBytesRecvd - The pointer to the user BytesRecvd parameter.
  1081.  
  1082.     UserFlags - A pointer to the user flags argument.
  1083.  
  1084.     UserTo - A pointer to the user sockaddr structure.
  1085.  
  1086.     UserToLen - The length of the user sockaddr structure.
  1087.  
  1088.     UserOverlappedStruct - The user overlapped struct pointer.
  1089.  
  1090.     UserCompletionRoutine - The user overlapped completion routine.
  1091.  
  1092.     UserThreadId - The user thread ID.
  1093.  
  1094.     InternalBuffers - A pointer to our internal buffer(s).
  1095.  
  1096.     InternalBufferCount - The number of internal buffers.
  1097.  
  1098.     Errno - A pointer to the user errno parameter.
  1099.  
  1100. Return Value:
  1101.  
  1102.     NO_ERROR on success else a valid winsock2 error code.
  1103.  
  1104. --*/
  1105. {
  1106.     INT                       ReturnCode;
  1107.     PINTERNALOVERLAPPEDSTRUCT OverlappedStruct;
  1108.  
  1109.     ReturnCode = SOCKET_ERROR;
  1110.     *Errno = WSAENOBUFS;
  1111.  
  1112.     OverlappedStruct =
  1113.         gOverlappedManager->AllocateOverlappedStruct();
  1114.     if (OverlappedStruct){
  1115.         OverlappedStruct->iolOperationType = WSP_SENDTO;
  1116.         OverlappedStruct->iolSocket = Socket->GetSocketHandle ();
  1117.         OverlappedStruct->iolProvider = Socket->GetDProvider();
  1118.         OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket ();
  1119.         OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct;
  1120.         OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine;
  1121.         OverlappedStruct->iolUserThreadId = *UserThreadId;
  1122.         if (UserBufferCount<=MAX_FAST_BUFS)
  1123.             memcpy (OverlappedStruct->iolUserBuffers, UserBuffers,
  1124.                         sizeof (WSABUF)*UserBufferCount);
  1125.         else {
  1126.             OverlappedStruct->iolpUserBuffers = new WSABUF[UserBufferCount];
  1127.             if (OverlappedStruct->iolpUserBuffers==NULL) {
  1128.                 gOverlappedManager->FreeOverlappedStruct (
  1129.                         &OverlappedStruct->iolInternalOverlappedStruct);
  1130.                 return ReturnCode;
  1131.             }
  1132.             memcpy (OverlappedStruct->iolpUserBuffers, UserBuffers,
  1133.                         sizeof (WSABUF)*UserBufferCount);
  1134.         }
  1135.         OverlappedStruct->iolUserBufferCount = UserBufferCount;
  1136.         OverlappedStruct->iolFlags = UserFlags;
  1137.         OverlappedStruct->iolSockAddr = (struct sockaddr FAR *)UserTo;
  1138.         OverlappedStruct->iolSockAddrLen = UserToLen;
  1139.  
  1140.         AddOverlappedOperation(
  1141.             Socket,
  1142.             OverlappedStruct);
  1143.  
  1144.         *Errno = WSA_IO_PENDING;
  1145.     } //if
  1146.     return(ReturnCode);
  1147. }
  1148.  
  1149. INT
  1150. DWORKERTHREAD::QueueOverlappedIoctl(
  1151.     PDSOCKET                           Socket,
  1152.     DWORD                              dwIoControlCode,
  1153.     LPVOID                             lpvInBuffer,
  1154.     DWORD                              cbInBuffer,
  1155.     LPVOID                             lpvOutBuffer,
  1156.     DWORD                              cbOutBuffer,
  1157.     LPDWORD                            lpcbBytesReturned,
  1158.     LPWSAOVERLAPPED                    UserOverlappedStruct,
  1159.     LPWSAOVERLAPPED_COMPLETION_ROUTINE UserCompletionRoutine,
  1160.     LPWSATHREADID                      UserThreadId,
  1161.     LPINT                              Errno
  1162.     )
  1163. /*++
  1164.  
  1165. Routine Description:
  1166.  
  1167.     this routine allocates an internal overlapped structure stores its
  1168.     arguments in the allocated structure and enqueues the structure for the
  1169.     worker thread to complet the I/O operation.
  1170.  
  1171. Arguments:
  1172.  
  1173.     Socket      - Socket object
  1174.  
  1175.     UserBuffers - The pointer to the user buffer(s).
  1176.  
  1177.     UserBufferCount - The number of user buffers.
  1178.  
  1179.     UserBytesRecvd - The pointer to the user BytesRecvd parameter.
  1180.  
  1181.     UserFlags - A pointer to the user flags argument.
  1182.  
  1183.     UserTo - A pointer to the user sockaddr structure.
  1184.  
  1185.     UserToLen - The length of the user sockaddr structure.
  1186.  
  1187.     UserOverlappedStruct - The user overlapped struct pointer.
  1188.  
  1189.     UserCompletionRoutine - The user overlapped completion routine.
  1190.  
  1191.     UserThreadId - The user thread ID.
  1192.  
  1193.     InternalBuffers - A pointer to our internal buffer(s).
  1194.  
  1195.     InternalBufferCount - The number of internal buffers.
  1196.  
  1197.     Errno - A pointer to the user errno parameter.
  1198.  
  1199. Return Value:
  1200.  
  1201.     NO_ERROR on success else a valid winsock2 error code.
  1202.  
  1203. --*/
  1204. {
  1205.     INT                       ReturnCode;
  1206.     PINTERNALOVERLAPPEDSTRUCT OverlappedStruct;
  1207.  
  1208.     ReturnCode = SOCKET_ERROR;
  1209.     *Errno = WSAENOBUFS;
  1210.  
  1211.     OverlappedStruct =
  1212.         gOverlappedManager->AllocateOverlappedStruct();
  1213.     if (OverlappedStruct){
  1214.         OverlappedStruct->iolOperationType = WSP_IOCTL;
  1215.         OverlappedStruct->iolSocket = Socket->GetSocketHandle ();
  1216.         OverlappedStruct->iolProvider = Socket->GetDProvider();
  1217.         OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket ();
  1218.         OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct;
  1219.         OverlappedStruct->iolUserCompletionRoutine = UserCompletionRoutine;
  1220.         OverlappedStruct->iolUserThreadId = *UserThreadId;
  1221.         OverlappedStruct->iolInputBuffer = lpvInBuffer;
  1222.         OverlappedStruct->iolInputBufferLength = cbInBuffer;
  1223.         OverlappedStruct->iolOutputBuffer = lpvOutBuffer;
  1224.         OverlappedStruct->iolOutputBufferLength = cbOutBuffer;
  1225.         OverlappedStruct->iolIoControlCode = dwIoControlCode;
  1226.  
  1227.         AddOverlappedOperation(
  1228.             Socket,
  1229.             OverlappedStruct);
  1230.  
  1231.         *Errno = WSA_IO_PENDING;
  1232.     } //if
  1233.     return(ReturnCode);
  1234. }
  1235.  
  1236.  
  1237.  
  1238. INT
  1239. DWORKERTHREAD::QueueOverlappedAcceptEx(
  1240.     PDSOCKET                           ListenSocket,
  1241.     PDSOCKET                           AcceptSocket,
  1242.     LPVOID                               lpOutputBuffer,
  1243.     DWORD                               dwReceiveDataLength,
  1244.     DWORD                               dwLocalAddressLength,
  1245.     DWORD                               dwRemoteAddressLength,
  1246.     LPWSAOVERLAPPED                       UserOverlappedStruct,
  1247.     LPINT                               Errno
  1248.     ) {
  1249.     INT                       ReturnCode;
  1250.     PINTERNALOVERLAPPEDSTRUCT OverlappedStruct;
  1251.  
  1252.     ReturnCode = SOCKET_ERROR;
  1253.     *Errno = WSAENOBUFS;
  1254.  
  1255.     OverlappedStruct =
  1256.         gOverlappedManager->AllocateOverlappedStruct();
  1257.     if (OverlappedStruct){
  1258.         OverlappedStruct->iolOperationType = ACCEPT_EX;
  1259.         OverlappedStruct->iolSocket = ListenSocket->GetSocketHandle ();
  1260.         OverlappedStruct->iolProvider = ListenSocket->GetDProvider();
  1261.         OverlappedStruct->iolListenSocket = ListenSocket->GetProviderSocket ();
  1262.         OverlappedStruct->iolAcceptSocket = AcceptSocket->GetProviderSocket ();
  1263.         OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct;
  1264.         OverlappedStruct->iolUserCompletionRoutine = NULL;
  1265.         OverlappedStruct->iolOutputBuffer = lpOutputBuffer;
  1266.         OverlappedStruct->iolOutputBufferLength = dwReceiveDataLength;
  1267.         OverlappedStruct->iolLocalAddressLength = dwLocalAddressLength;
  1268.         OverlappedStruct->iolRemoteAddressLength = dwRemoteAddressLength;
  1269.  
  1270.         AddOverlappedOperation(
  1271.             ListenSocket,
  1272.             OverlappedStruct);
  1273.  
  1274.         *Errno = WSA_IO_PENDING;
  1275.     } //if
  1276.     return(ReturnCode);
  1277. }
  1278.  
  1279.  
  1280. INT
  1281. DWORKERTHREAD::QueueOverlappedTransmitFile(
  1282.     PDSOCKET                            Socket,
  1283.     HANDLE                                hFile,
  1284.     DWORD                                nNumberOfBytesToWrite,
  1285.     DWORD                                nNumberOfBytesPerSend,
  1286.     LPWSAOVERLAPPED                        UserOverlappedStruct,
  1287.     LPTRANSMIT_FILE_BUFFERS                lpTransmitBuffers,
  1288.     DWORD                                dwReserved,
  1289.     LPINT                               Errno
  1290.     )
  1291. {
  1292.     INT                       ReturnCode;
  1293.     PINTERNALOVERLAPPEDSTRUCT OverlappedStruct;
  1294.  
  1295.     ReturnCode = SOCKET_ERROR;
  1296.     *Errno = WSAENOBUFS;
  1297.  
  1298.     OverlappedStruct =
  1299.         gOverlappedManager->AllocateOverlappedStruct();
  1300.     if (OverlappedStruct){
  1301.         OverlappedStruct->iolOperationType = TRANSMIT_FILE;
  1302.         OverlappedStruct->iolSocket = Socket->GetSocketHandle ();
  1303.         OverlappedStruct->iolProvider = Socket->GetDProvider();
  1304.         OverlappedStruct->iolProviderSocket = Socket->GetProviderSocket ();
  1305.         OverlappedStruct->iolUserOverlappedStruct = UserOverlappedStruct;
  1306.         OverlappedStruct->iolUserCompletionRoutine = NULL;
  1307.         OverlappedStruct->iolFileHandle = hFile;
  1308.         OverlappedStruct->iolBytesToWrite = nNumberOfBytesToWrite;
  1309.         OverlappedStruct->iolBytesPerSend = nNumberOfBytesPerSend;
  1310.         if (lpTransmitBuffers)
  1311.             OverlappedStruct->iolTransmitBuffers = *lpTransmitBuffers;
  1312.         else
  1313.             OverlappedStruct->iolTransmitBuffers.HeadLength =
  1314.                 OverlappedStruct->iolTransmitBuffers.TailLength = 0;
  1315.  
  1316.         OverlappedStruct->iolReserved = dwReserved;
  1317.         AddOverlappedOperation(
  1318.             Socket,
  1319.             OverlappedStruct);
  1320.  
  1321.         *Errno = WSA_IO_PENDING;
  1322.     } //if
  1323.     return(ReturnCode);
  1324. }
  1325.  
  1326. VOID
  1327. DWORKERTHREAD::AddOverlappedOperation(
  1328.     IN PDSOCKET                  Socket,
  1329.     IN PINTERNALOVERLAPPEDSTRUCT OverlappedOperation
  1330.     )
  1331. /*++
  1332. Routine Description:
  1333.  
  1334.     This routine adds an internal overlapped structure to the queue of requests
  1335.     to be completed by the worker thread.
  1336.  
  1337. Arguments:
  1338.  
  1339.     Socket              - A pointer to socket object
  1340.     OverlappedOperation - A pointer to an internal overlapped structure that
  1341.                           describes the operation to be performed by the worker
  1342.                           thread.
  1343.  
  1344. Return Value:
  1345.  
  1346.     NONE
  1347. --*/
  1348. {
  1349.  
  1350.     // If we are using completion ports or user requested
  1351.     // completion via APC, initiate operation in the
  1352.     // context of the current thread
  1353.     if (m_completion_port!=NULL) {
  1354.         if (Socket->GetCompletionContext ()==INVALID_SOCKET) {
  1355.             CreateIoCompletionPort (
  1356.                 (HANDLE)OverlappedOperation->iolProviderSocket,
  1357.                 m_completion_port,
  1358.                 OverlappedOperation->iolSocket,
  1359.                 0);
  1360.             Socket->SetCompletionContext (OverlappedOperation->iolSocket);
  1361.         }
  1362.         InitiateOverlappedOperation (
  1363.             OverlappedOperation,
  1364.             NULL,
  1365.             &OverlappedOperation->iolUserThreadId);
  1366.     }
  1367.     else {
  1368.         EnterCriticalSection(&m_overlapped_operation_queue_lock);
  1369.         InsertTailList(
  1370.             &m_overlapped_operation_queue,
  1371.             &OverlappedOperation->iolListLinkage);
  1372.         LeaveCriticalSection(&m_overlapped_operation_queue_lock);
  1373.         ReleaseSemaphore (m_wakeup_semaphore, 1, NULL);
  1374.     }
  1375. }
  1376.  
  1377.  
  1378. PINTERNALOVERLAPPEDSTRUCT
  1379. DWORKERTHREAD::NextOverlappedOperation()
  1380. /*++
  1381. Routine Description:
  1382.  
  1383.     This routine returns the first internal overlapped structure from the queue
  1384.     of requests to be completed by the worker thread.
  1385.  
  1386. Arguments:
  1387.  
  1388.     NONE
  1389.  
  1390. Return Value:
  1391.  
  1392.     A pointer to an internal overlapped structure or NULL
  1393.  
  1394. --*/
  1395. {
  1396.     PINTERNALOVERLAPPEDSTRUCT ReturnValue;
  1397.     PLIST_ENTRY               ListEntry;
  1398.  
  1399.     ReturnValue = NULL;
  1400.  
  1401.     EnterCriticalSection(&m_overlapped_operation_queue_lock);
  1402.  
  1403.     if (!IsListEmpty(&m_overlapped_operation_queue)){
  1404.         ListEntry = RemoveHeadList(
  1405.             &m_overlapped_operation_queue);
  1406.         ReturnValue = CONTAINING_RECORD(
  1407.             ListEntry,
  1408.             INTERNALOVERLAPPEDSTRUCT,
  1409.             iolListLinkage);
  1410.     } //if
  1411.  
  1412.     LeaveCriticalSection(&m_overlapped_operation_queue_lock);
  1413.     return(ReturnValue);
  1414. }
  1415.  
  1416.  
  1417.